home *** CD-ROM | disk | FTP | other *** search
- // Copyright 1994 by Jon Dart. All Rights Reserved.
-
- // main program.
-
- #include "chess.h"
- #include "bhash.h"
- #include "bearing.h"
- #include "movegen.h"
- #include "msgs.h"
- #include "srclimit.h"
- #include "timectrl.h"
- #include "preferen.h"
- #include "display.h"
- #include "promotio.h"
- #include "showmove.h"
- #include "options.h"
- #include "notation.h"
- #include "movearr.h"
- #include "hint.h"
- #include "globals.h"
- #include <fstream.h>
- #include <ctype.h>
- #include <string.h>
- #include <time.h>
-
- #define MAIN_TIMER 1
-
- // global variables
-
- Book *opening_book = NULL;
- WPMainWin *appWin = NULL;
- Move_Array *game_moves = NULL;
- Options *global_options = NULL;
- Clock *the_clock = NULL;
- static char tmpbuf[256];
-
- Chess::Chess()
- {
- createWin("Arasan");
- WPRect area;
- getWindowRect(area);
- display = new Display(this,area);
- the_clock = new Clock(getHwnd());
- setTimer(MAIN_TIMER,1000);
- global_options = new Options();
- setup_clock_initially();
- game_moves = new Move_Array();
- opening_book = new Book();
- searcher = new Search;
- use_book = True;
- users_move = True;
- *last_move_image = '\0';
- last_cmd = MYIDM_DUMMY;
- no_prev_search = True;
- log.write_header();
- quitting = False;
- }
-
- Chess::~Chess()
- {
- quitting = True;
- killTimer(MAIN_TIMER);
- if (searching)
- {
- searcher->terminate_now();
- }
- delete the_clock;
- delete display;
- delete global_options;
- delete game_moves;
- delete opening_book;
- delete searcher;
- }
-
- void Chess::reset()
- {
- delete game_moves;
- game_moves = new Move_Array();
- log.clear();
- log.write_header();
- last_move.MakeNull();
- predicted_move.MakeNull();
- *last_move_image = '\0';
- use_book = True;
- users_move = True;
- last_cmd = MYIDM_DUMMY;
- setup_clock_initially();
- the_clock->reset();
- no_prev_search = True;
- computer_plays(current_board.OppositeSide());
- {
- WPWinDC dc = this;
- display->clear_status_line(dc);
- display->clear_move_area(dc);
- display->clear_search_counts(dc);
- }
- stats.clear();
- }
-
- void Chess::paint( WPPaintStruct &ps)
- {
- WPRect clientArea = this;
- display->set_size(clientArea);
- WPRect drawArea;
- ps.getPaintRect(drawArea);
- display->draw_board(ps,current_board,&drawArea);
- show_side();
- show_last_move();
- the_clock->show_time(White);
- the_clock->show_time(Black);
- if (!no_prev_search)
- Display::show_search_counts(getHwnd(),stats.max_depth,
- stats.num_pos);
- WPWinDC dc(this);
- display->show_status(dc,stats);
- validate();
- }
-
- static int legal_move(const Board &board, const Square &start,
- const Square &dest)
- {
- // do a little basic sanity checking:
- if (!start.OnBoard() || !dest.OnBoard() || board[start].IsEmpty())
- return False;
-
- ExtendedMove emove(board,start,dest);
- Move moves[Move_Generator::MaxMoves];
- Move_Generator mg( board, 0, Move::NullMove() );
- int found = 0;
- int n = mg.Generate_Moves(moves, False);
-
- for (int i = 0; i < n; i++)
- {
- if (moves[i].StartSquare() == emove.StartSquare() &&
- moves[i].DestSquare() == emove.DestSquare())
- {
- found++;
- break;
- }
- }
- if (!found)
- return False;
- else
- {
- // check for king en prise
- Board board_copy(board);
- const ColorType side = board.Side();
- board_copy.MakeMove(emove);
- return board_copy.num_attacks(
- board_copy.KingPos(side),OppositeColor(side)) == 0;
-
- }
- }
-
- // handle updating to the next time control, if necessary
- void Chess::update_time()
- {
- if (the_clock->time_is_up())
- return;
- // We already made the move and changed the side to move,
- // so use "oppside" for the data we need:
- const ColorType oppside = current_board.OppositeSide();
- Time_Info &my_ti = ti[oppside];
- if (my_ti.get_search_type() == Tournament)
- {
- // see if we made time control
- Search_Limit limit = my_ti.get_search_limit();
- if (((game_moves->num_moves()-1)/2) - my_ti.get_last_time_control()
- + 1 == limit.limit.moves)
- {
- // we made it, update to next time control
- int period = my_ti.get_period();
- time_t bonus = the_clock->get_limit(oppside)
- - the_clock->elapsed_time(oppside);
- my_ti.set_bonus(bonus);
- if (++period < Max_Time_Controls)
- {
- Time_Control next_tc =
- global_options->get_time_control((Control)period);
- if (next_tc.get_search_type() != None)
- {
- my_ti.set_time_control(next_tc);
- }
- }
- my_ti.set_last_time_control(1+((game_moves->num_moves()-1)/2));
- my_ti.set_period(period);
- setup_clock(oppside);
- }
- }
- the_clock->start(current_board.Side());
- }
-
- void Chess::update_board( const ExtendedMove &emove,
- const Search::Statistics *stats,
- const Boolean update_log)
- {
- WPWinDC dc(this);
- if (stats)
- display->show_status(dc,*stats);
-
- if (!emove.IsNull())
- {
- Notation::Image(current_board,emove,last_move_image);
- if (update_log)
- log.add_move(current_board,last_move,last_move_image,stats,True);
- current_board.MakeMove(emove);
- show_last_move( last_move_image ); // must call after add_move
- game_moves->add_move(current_board,emove);
-
- display->draw_square(dc,emove.StartSquare());
- display->draw_square(dc,emove.DestSquare());
- display->draw_piece(dc,emove.DestSquare(),
- current_board[emove.DestSquare()]);
- Square target, oldrooksq, newrooksq;
- switch( emove.Special())
- {
- case ExtendedMove::Normal:
- break;
- case ExtendedMove::EnPassant:
- target = emove.DestSquare();
- if (emove.PieceMoved().Color() == White)
- target += RankIncr;
- else
- target -= RankIncr;
- display->draw_square(dc,target);
- break;
- case ExtendedMove::KCastle:
- oldrooksq = emove.StartSquare() + 3;
- newrooksq = emove.StartSquare() + 1;
- display->draw_square(dc,oldrooksq);
- display->draw_piece(dc,newrooksq,current_board[newrooksq]);
- break;
- case ExtendedMove::QCastle:
- oldrooksq = emove.StartSquare() - 4;
- newrooksq = emove.StartSquare() - 1;
- display->draw_square(dc,oldrooksq);
- // must re-draw new rook square, so we get the right brush:
- display->draw_square(dc,newrooksq);
- display->draw_piece(dc,newrooksq,current_board[newrooksq]);
- break;
- case ExtendedMove::Promotion:
- display->draw_piece(dc,emove.DestSquare(),
- Piece(emove.PromoteTo(),emove.PieceMoved().Color()));
- break;
- }
- display->show_side(dc,current_board.Side());
- users_move = !users_move;
- }
-
- if (stats)
- {
- switch (stats->state)
- {
- case Search::Checkmate:
- MsgBox("Checkmate!");
- the_clock->stop();
- break;
- case Search::Stalemate:
- MsgBox("Stalemate!");
- the_clock->stop();
- break;
- case Search::Draw:
- MsgBox("Draw!");
- the_clock->stop();
- break;
- case Search::Resigns:
- {
- char msg[40];
- wsprintf(msg,"%s resigns!",
- Image(current_board.OppositeSide()));
- MsgBox(msg);
- }
- the_clock->stop();
- break;
- default:
- update_time();
- }
- }
- else
- {
- update_time();
- }
-
- }
-
- void Chess::compute_move(Board &board, const Time_Info &ti,
- const Boolean background,
- Search::Statistics &stats,
- ExtendedMove &emove)
- {
- searching = True;
-
- if (global_options->use_book() && use_book)
- {
- Move move = opening_book->book_move(current_board);
- if (!move.IsNull())
- {
- searching = False;
- emove = ExtendedMove(current_board,move);
- if (current_board.CheckStatus() == Board::InCheck)
- stats.state = Search::Check;
- else
- stats.state = Search::Normal;
- stats.value = 0;
- stats.elapsed_time = 0;
- stats.num_moves = stats.num_pos = 0L;
- if (background)
- predicted_move = ReversibleMove(current_board,emove);
- else
- last_move = ReversibleMove(current_board,emove);
- // suppress display of search statistics:
- no_prev_search = True;
- return;
- }
- }
-
- // no book move
-
- // The search routine has its own timer, so we disable ours.
- killTimer(MAIN_TIMER);
-
- // We may be able to use the results of a search we did
- // on our opponent's time:
- Boolean previous_search = !users_move &&
- global_options->think_when_idle();
- Move best =
- searcher->find_best_move(getHwnd(),board,
- ti,
- background,
- stats,
- predicted_move,
- previous_search);
- emove = ExtendedMove(current_board,best);
- setTimer(MAIN_TIMER,1000);
- if (!users_move && stats.state != Search::Terminated &&
- global_options->beep_after_move())
- MessageBeep(1);
- if (background)
- predicted_move = ReversibleMove(current_board,emove);
- else
- last_move = ReversibleMove(current_board,emove);
- searching = False;
- }
-
- BOOL Chess::mouse( int msg, WPPoint p, WORD /*flags*/ )
- {
- Square dest;
- switch (msg)
- {
- case WM_LBUTTONDOWN:
- if (!users_move)
- {
- // not the user's move
- if (global_options->beep_on_error())
- MessageBeep(0);
- start_square = Square::Invalid();
- return FALSE;
- }
- // find out where we are on the board:
- start_square = display->mouse_loc(p);
- if (current_board[start_square].IsEmpty())
- {
- start_square = Square::Invalid();
- return FALSE; // no piece on this square
- }
- else
- {
- WPWinDC dc(this);
- display->highlight_square(dc,start_square);
- }
- break;
- case WM_LBUTTONUP:
- // find out where we are on the board:
- dest = display->mouse_loc(p);
- if (!dest.OnBoard())
- return FALSE;
- if (!users_move || start_square.IsInvalid())
- {
- return TRUE; // ignore event
- }
- if ( !legal_move(current_board,start_square,dest))
- {
- if (global_options->beep_on_error())
- MessageBeep(8);
- }
- else
- {
- // move is legal
- WPWinDC dc(this);
- display->unhighlight_square(dc,start_square);
- last_move = ReversibleMove(current_board,start_square,dest);
- if (searching)
- {
- // tell the search to terminate
- last_cmd = MYIDM_MAKEUSERMOVE;
- searcher->terminate_now();
- }
- // if we are searching, this message won't be processed
- // until we are done.
- PostMessage(getHwnd(),WM_COMMAND,MYIDM_MAKEUSERMOVE,0L);
- return TRUE;
- }
- break;
- default:
- break;
- }
- return TRUE;
- }
-
- BOOL Chess::timer( int id )
- {
- if (id == MAIN_TIMER)
- {
- the_clock->update();
- }
- return TRUE;
- }
-
- BOOL Chess::sized(WPRect &box, WORD)
- {
- display->set_size(box);
- return FALSE;
- }
-
- BOOL Chess::menuInit(WPMenu &menu)
- {
- WPMenu mainMenu = this;
- if (menu == mainMenu)
- {
- if (the_clock->is_running())
- {
- mainMenu.enableItem(MYIDM_PAUSE,TRUE);
- mainMenu.enableItem(MYIDM_RESUME,FALSE);
- }
- else if (the_clock->is_stopped())
- {
- mainMenu.enableItem(MYIDM_PAUSE,FALSE);
- mainMenu.enableItem(MYIDM_RESUME,FALSE);
- }
- else
- {
- mainMenu.enableItem(MYIDM_PAUSE,FALSE);
- mainMenu.enableItem(MYIDM_RESUME,TRUE);
- }
- if (users_move)
- mainMenu.enableItem(MYIDM_HINT,TRUE);
- else
- mainMenu.enableItem(MYIDM_HINT,FALSE);
- return TRUE;
- }
- return FALSE;
- }
-
- BOOL Chess::command( int id, WORD msg )
- {
- // overrides base version, handles menu selections
-
- last_cmd = id;
- if (id >= WM_USER)
- {
- if (quitting) // shutting down, ignore user commands
- return TRUE;
- if (searching)
- {
- switch (id)
- {
- // These commands don't modify the board, the side to move,
- // or the search parameters. So there is no need to stop
- // any search in progress.
- case MYIDM_SHOWGAME:
- case MYIDM_ROTATEBOARD:
- case MYIDM_PAUSE:
- case MYIDM_RESUME:
- case MYIDM_SAVEBOARD:
- case MYIDM_PREFERENCES:
- case MYIDM_RESTART_SEARCH:
- case MYIDM_HINT:
- case MYIDM_MAKEUSERMOVE:
- case MYIDM_DUMMY:
- break;
- default:
- // For all other commands, we first terminate the search. All
- // commands will be ignored until the search terminates. At
- // that point, we will execute 'last_cmd'.
- searcher->terminate_now();
- PostMessage(getHwnd(),WM_COMMAND,id,0L);
- return TRUE;
- }
- }
- }
- Square start_square,dest;
- switch (id)
- {
- case MYIDM_DUMMY:
- break;
- case MYIDM_LOADBOARD:
- *tmpbuf = '\0';
- {
- WPDlgFileOpen dlg(this,tmpbuf,"Load Board");
- char filter[] = "Board file (*.fen)\0*.fen\0";
- dlg.setFilter(filter);
- if (!dlg.createWin())
- {
- return FALSE;
- }
- if (*tmpbuf)
- {
- ifstream pos_file( tmpbuf,
- ios::in | ios::noreplace | ios::binary );
- if (pos_file.good())
- {
- pos_file >> current_board ;
- if (!pos_file)
- {
- MessageBox(NULL,"Bad format in file!",
- "Load Board",MB_OK);
- current_board.Reset();
- }
- else
- use_book = False;
- pos_file.close();
- }
- char *msg = new char[300];
- wsprintf(msg,"== %s loaded from disk",tmpbuf);
- log.write(msg);
- log.write_eol();
- delete [] msg;
- reset();
- draw_board();
- show_side();
- }
- }
- return TRUE;
- case MYIDM_SAVEBOARD:
- {
- WPDlgFileSaveAs save_dlg(this,tmpbuf,"Save Board");
- char filter[] = "Board file (*.fen)\0*.fen\0";
- save_dlg.setFilter(filter);
- if (!save_dlg.createWin())
- {
- return FALSE;
- }
- if (*tmpbuf)
- {
- ofstream ofile( tmpbuf,ios::out | ios::noreplace | ios::binary );
- if (ofile.good())
- {
- ofile << current_board;
- if (!ofile)
- MessageBox(NULL,"Error saving file!","Save Board",MB_OK);
- ofile.close();
- }
- }
- }
- return TRUE;
- case MYIDM_LOADGAME:
- // Games are stored in PGN notation.
- *tmpbuf = '\0';
- {
- WPDlgFileOpen dlg(this,tmpbuf,"Load Game");
- char filter[] = "Game file (*.pgn)\0*.pgn\0";
- dlg.setFilter(filter);
- if (!dlg.createWin())
- {
- return FALSE;
- }
- if (*tmpbuf)
- {
- current_board.Reset();
- log.clear();
- ifstream game_file( tmpbuf, ios::in );
- ColorType side = White;
- int c;
- // skip header, if any:
- while (game_file.good() && (c = game_file.get()) != EOF)
- {
- if (c=='[')
- {
- game_file.ignore(255,']');
- continue;
- }
- else if (c == '1')
- {
- game_file.putback(c);
- break;
- }
- }
- while (game_file.good() && !game_file.eof())
- {
- // skip to next move
- for (;;)
- {
- c = game_file.get();
- if (isalpha(c) || game_file.eof())
- break;
- }
- // collect the move text
- char movebuf[20];
- int i = 0;
- while (i < 19 && !game_file.eof() &&
- !isspace(c) && (c != '\n'))
- {
- movebuf[i] = c; ++i;
- c = game_file.get();
- }
- if (i == 0)
- break;
- movebuf[i] = '\0';
- // parse the move
- Move m = Notation::Value(current_board,side,movebuf);
- if (m.IsNull() ||
- !legal_move(current_board,m.StartSquare(),
- m.DestSquare()))
- {
- char msg[80];
- wsprintf(msg,"Illegal or invalid move: %s",
- movebuf);
- MessageBox(NULL,msg,"",MB_OK);
- log.clear();
- break;
- }
- else
- {
- //MessageBox(NULL,m.Image(),"",MB_OK);
- ExtendedMove emove(current_board,m);
- ReversibleMove rmove(current_board,emove);
- log.add_move(current_board,rmove,movebuf,NULL,
- False);
- current_board.MakeMove(rmove);
- }
- side = OppositeColor(side);
- }
- game_file.close();
- current_board.Reset();
- log.reset();
- last_move.MakeNull();
- predicted_move.MakeNull();
- *last_move_image = '\0';
- use_book = True;
- users_move = True;
- last_cmd = MYIDM_DUMMY;
- the_clock->reset();
- no_prev_search = True;
- computer_plays(Black);
- {
- WPWinDC dc = this;
- display->clear_status_line(dc);
- display->clear_move_area(dc);
- display->clear_search_counts(dc);
- }
- stats.clear();
- draw_board();
- the_clock->start(current_board.Side());
- }
- return TRUE;
- }
- case MYIDM_SAVEGAME:
- {
- WPDlgFileSaveAs save_dlg(this,tmpbuf,"Save Game");
- char filter[] = "Game file (*.pgn)\0*.pgn\0";
- save_dlg.setFilter(filter);
- if (!save_dlg.createWin())
- {
- return FALSE;
- }
- if (*tmpbuf)
- {
- ofstream ofile( tmpbuf,ios::out | ios::trunc );
- if (ofile.good())
- {
- // Write standard PGN header.
- time_t tm = time(NULL);
- struct tm *t = localtime(&tm);
- char string[15];
- ofile << "[Event \"?\"]" << endl;
- ofile << "[Site \"?\"]" << endl;
- wsprintf(string,"%d.%02d.%02d",t->tm_year,t->tm_mon+1,
- t->tm_mday);
- ofile << "[Date \"" << string << "\"]" << endl;
- ofile << "[Round \"nil\"]" << endl;
- if (computer_side == White)
- {
- ofile << "[White \"" << "Arasan " <<
- Version << "\"]" << endl;
- ofile << "[Black \"?\"]" << endl;
- }
- else
- {
- ofile << "[White \"?\"]" << endl;
- ofile << "[Black \"" << "Arasan " <<
- Version << "\"]" << endl;
- }
- ofile << "[Result \"*\"]" << endl << endl;
-
- // Write game moves.
- const unsigned size = log.num_moves();
- char buf[80];
- *buf = '\0';
- char num[10];
- int last = 0;
- int num_image_size;
- for (int i = 0; i < size; i++)
- {
- Log_Entry &e = log[i];
- num_image_size = 0;
- *num = '\0';
- if (i % 2 == 0)
- {
- wsprintf(num,"%d. ",(i/2)+1);
- num_image_size = strlen(num);
- }
- const int image_size = strlen(e.image());
- if (last + image_size + num_image_size + 1 >= 70)
- {
- buf[last] = '\0';
- ofile << buf << endl;
- last = 0;
- *buf = '\0';
- }
- if (last != 0)
- strcat(buf," ");
- strcat(buf,num);
- strcat(buf,e.image());
- last = strlen(buf);
- }
- if (last)
- {
- buf[last] = '\0';
- ofile << buf << endl;
- }
- if (!ofile)
- MessageBox(NULL,"Error saving file!","Save Game",MB_OK);
- ofile.close();
- }
- }
- }
-
- return TRUE;
- case MYIDM_EXIT:
- WPMainWin::close();
- return TRUE;
- case MYIDM_BACKGROUND_COMPUTE:
- {
- if (!global_options->think_when_idle())
- return TRUE;
- // We do a search to maximum depth. We don't really
- // expect to finish this; we will be interrupted
- // by a user command.
- Search_Limit limit;
- limit.max_ply = Constants::MaxPly;
- ExtendedMove emove;
- Search::Statistics tmp_stats;
- Time_Info ti;
- ti.set_time_control(Time_Control( Fixed_Ply, limit ));
- ti.set_period(0);
- compute_move(current_board, ti,
- True, tmp_stats, emove);
- return TRUE;
- }
- case MYIDM_RESTART_SEARCH:
- case MYIDM_COMPUTE:
- {
- ExtendedMove emove;
- {
- WPWinDC dc(this);
- display->clear_search_counts(dc);
- display->clear_status_line(dc);
- //display->clear_move_area(dc);
- }
- no_prev_search = False;
- compute_move(current_board,ti[current_board.Side()],
- False, stats, emove );
- if (stats.state != Search::Terminated ||
- last_cmd == MYIDM_COMPUTE)
- {
- last_move = ReversibleMove(current_board,emove);
- update_board(emove,&stats,True);
- if (users_move && global_options->think_when_idle())
- PostMessage(getHwnd(),WM_COMMAND,MYIDM_BACKGROUND_COMPUTE,0L);
- }
- return TRUE;
- }
- case MYIDM_MAKEUSERMOVE:
- {
- start_square = last_move.StartSquare();
- dest = last_move.DestSquare();
- ExtendedMove emove;
- if (current_board[start_square].Type() == Piece::Pawn &&
- dest.Rank(current_board.Side()) == 8)
- {
- // promotion, prompt for piece to promote to
- PromotionOption popt;
- popt.piece = 0; // default is 0 (Queen)
- PromotionDialog *pdlg = new PromotionDialog(this,&popt);
- if (pdlg->returnCode() == IDCANCEL)
- {
- delete pdlg;
- return TRUE;
- }
- delete pdlg;
- Move m;
- switch (popt.piece)
- {
- case 0: m = Move(start_square,dest,Piece::Queen); break;
- case 1: m = Move(start_square,dest,Piece::Rook); break;
- case 2: m = Move(start_square,dest,Piece::Bishop); break;
- case 3: m = Move(start_square,dest,Piece::Knight); break;
- }
- emove = ExtendedMove(current_board,m);
- }
- else
- emove = ExtendedMove(current_board,start_square,dest);
- update_board(emove,NULL,True);
-
- // calculate a reply move:
- PostMessage(getHwnd(),WM_COMMAND,MYIDM_COMPUTE,0L);
- return TRUE;
- }
- case MYIDM_TAKEBACK:
- if (log.current() == 0)
- {
- MessageBox(NULL,"No moves to take back.","",MB_OK);
- return TRUE;
- }
- else
- {
- current_board.UndoMove(log[log.current()-1].move());
- log.back_up();
- game_moves->remove_move();
- if (log.current())
- {
- last_move = log[log.current()-1].move();
- strcpy(last_move_image,log[log.current()-1].image());
- }
- else
- {
- last_move.MakeNull();
- *last_move_image = '\0';
- }
- stats.clear();
- show_last_move();
- // should really be smarter about updating the board:
- draw_board();
- {
- WPWinDC dc(this);
- display->clear_search_counts(dc);
- display->clear_status_line(dc);
- }
- no_prev_search = True;
- the_clock->start(current_board.Side());
- users_move = !users_move;
- return TRUE;
- }
- case MYIDM_FORWARD:
- if (log.go_forward())
- {
- last_move = log.last_move();
- update_board(last_move,NULL,False);
- }
- return TRUE;
- case MYIDM_HINT:
- {
- HintDialog *dlg = new HintDialog(this,current_board);
- if (dlg->returnCode() == IDCANCEL)
- {
- delete dlg;
- return TRUE;
- }
- else
- {
- // got a move, execute it
- delete dlg;
- ExtendedMove emove(current_board,HintDialog::hintMove);
- last_move = ReversibleMove(current_board,emove);
- if (searching)
- {
- // tell the search to terminate
- last_cmd = MYIDM_MAKEUSERMOVE;
- searcher->terminate_now();
- }
- PostMessage(getHwnd(),WM_COMMAND,MYIDM_MAKEUSERMOVE,0L);
- return TRUE;
- }
- }
- case MYIDM_CHANGESIDES:
- current_board.Set_Side(current_board.OppositeSide());
- show_side();
- the_clock->start(current_board.Side());
- return TRUE;
- case MYIDM_PLAYWHITE:
- computer_plays( current_board.Side());
- users_move = !users_move;
- if (users_move)
- {
- if (global_options->think_when_idle())
- PostMessage(getHwnd(),WM_COMMAND,
- MYIDM_BACKGROUND_COMPUTE,0L);
- }
- else
- PostMessage(getHwnd(),WM_COMMAND,MYIDM_COMPUTE,0L);
- return TRUE;
- case MYIDM_ROTATEBOARD:
- display->set_turned(!display->is_turned());
- draw_board();
- return TRUE;
- case MYIDM_SHOWGAME:
- {
- ShowMovesDialog *sgdlg = new ShowMovesDialog(this,log);
- delete sgdlg;
- return TRUE;
- }
- case MYIDM_NEWGAME:
- current_board.Reset();
- draw_board();
- reset();
- use_book = True;
- the_clock->start(White);
- return TRUE;
- case MYIDM_PAUSE:
- the_clock->pause();
- return TRUE;
- case MYIDM_RESUME:
- the_clock->resume();
- return TRUE;
- case MYIDM_RESET:
- the_clock->reset();
- return TRUE;
- case MYIDM_SRCLIMITS:
- {
- Search_Limit_Options primary_options(global_options->get_time_control(First),First);
- Search_Limit_Options secondary_options(global_options->get_time_control(Second),Second);
- // Put the dialog box up.
- // Note : Windows++ requires it to be on the heap, not stack:
- SearchLimitDialog *sldlg = new SearchLimitDialog(this,
- &primary_options,&secondary_options);
- if( sldlg->isModified())
- {
- // update global_options with the new data
- Time_Control new_tc;
- primary_options.parse(new_tc,First);
- global_options->set_time_control(new_tc,First);
- char msg[100];
- wsprintf(msg,"=== Primary time control: %s",new_tc.Image());
- log.write(msg); log.write_eol();
- if (new_tc.get_search_type() == Tournament)
- {
- secondary_options.parse(new_tc,Second);
- wsprintf(msg,"=== Secondary time control: %s",new_tc.Image());
- log.write(msg); log.write_eol();
- }
- else
- {
- new_tc.set_search_type(None);
- }
- global_options->set_time_control(new_tc,Second);
- setup_clock_initially();
- if (!users_move && searching)
- {
- // restart the search with the new limits
- last_cmd = MYIDM_RESTART_SEARCH;
- searcher->terminate_now();
- }
- delete sldlg;
- return TRUE;
- }
- else return FALSE;
- }
- case MYIDM_PREFERENCES:
- {
- Preferences prefs;
- global_options->get_preferences(prefs);
- PreferencesDialog *pdlg = new PreferencesDialog(this,&prefs);
- if( pdlg->isModified())
- {
- global_options->update_preferences(prefs);
- }
- delete pdlg;
- return TRUE;
- }
- case MYIDM_LOSSONTIME:
- {
- char buf[50];
- wsprintf(buf,"%s loses on time!",Image(the_clock->get_side_to_move()));
- MsgBox(buf);
- return TRUE;
- }
- default:
- return WPMainWin::command(id,msg);
- }
- // shouldn't get here, but keep the compiler happy:
- return TRUE;
- }
-
- void Chess::draw_board()
- {
- WPWinDC dc(this);
- WPRect clientArea = this;
- display->draw_board(dc,current_board,&clientArea);
- }
-
- void Chess::show_side()
- {
- WPWinDC dc(this);
- display->show_side(dc,current_board.Side());
- }
-
- void Chess::show_last_move( char *move_image )
- {
- WPWinDC dc(this);
- display->show_move(dc,move_image,log.current());
- }
-
- void Chess::show_last_move()
- {
- WPWinDC dc(this);
- if (last_move.IsNull())
- display->clear_move_area(dc);
- else
- {
- display->show_move(dc,last_move_image,log.current());
- }
- }
-
- void Chess::computer_plays( const ColorType side )
- {
- computer_side = side;
- WPMenu menu = this;
- menu.checkItem(MYIDM_PLAYWHITE, side == White ? TRUE : FALSE,
- MF_BYCOMMAND );
- }
-
- void Chess::write_log(char *msg)
- {
- log.write(msg); log.write_eol();
- }
-
- // Call this when a time control is reached to reset clock options for one
- // side
- void Chess::setup_clock(const ColorType side)
- {
- const Search_Limit limits = ti[side].get_search_limit();
- switch (ti[side].get_search_type())
- {
- case Fixed_Ply:
- case Time_Limit:
- the_clock->count_up(); break;
- case Game:
- case Tournament:
- the_clock->count_down(
- limits.limit.minutes*60L+ti[side].get_bonus(),side);
- break;
- }
- }
-
- // Call this on startup and after clock options change
- void Chess::setup_clock_initially()
- {
- ti[White].set_time_control(global_options->get_time_control(First));
- ti[Black].set_time_control(global_options->get_time_control(First));
- ti[White].set_period(0);
- ti[Black].set_period(0);
- ti[White].set_bonus(0);
- ti[Black].set_bonus(0);
- setup_clock(White);
- setup_clock(Black);
- }
-
- void WPApp::main()
- {
- mainWin = appWin = new Chess;
- run();
- }
-
-